在上一篇文章中我們了解了 proxy pattern 的概念,也明白現今軟體架構有非常多適合應用這個 pattern 的 use cases。今天則想聚焦在 http proxy 的應用,並使用 Node.js 嘗試建立一個簡單的 proxy 出來。
在開始實作以前,想來講講 http proxy 常見的應用情形,我自己在專案中常見的 http proxy 主要功能是處理轉址、網路請求與 Authorization。架構完整的專案中,有可能會提供 development 版本的 API 與 production 版本的 API,通常兩種版本的 API 也會部署在不同的 domain 上面,但我們不希望在 client side 處理決定呼叫哪個 API 的邏輯(client 也不應該在意這件事),而這件事情就很適合放到 proxy server 處理,由 proxy 去決定要 call 哪個 API。至於 Authorization 我想是每個應用都會需要處理的狀況, client 發出 request 之後,會在 proxy 檢查是否擁有足夠的權限可以訪問該資源,如果檢查合格, proxy 再向目標發出請求,如果檢查結果為不符合權限,proxy 則可以執行如轉址(redirect)等相對應的動作。
接下來就直接進入實作的部分了,我們將使用 Node.js、express 搭配 http-proxy-middleware 這個第三方套件實作出一個簡易的 proxy,功能為將特定 route 的 request 導至呼叫 JSONPlaceholder API 這個第三方 API,可以拿取一些測試用的 data。
首先先創建一個新專案資料夾,執行 npm init -y 開啟一個 npm repo 並執行以下指令安裝我們需要的 dependencies。
$ yarn add express http-proxy-middleware
接著建立 app.js 檔案
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
// Create Express Server
const app = express();
// Configuration
const PORT = 3000;
const HOST = "localhost";
const API_SERVICE_URL = "https://jsonplaceholder.typicode.com";
// Proxy endpoints
app.use('/my-service', createProxyMiddleware({
target: API_SERVICE_URL,
changeOrigin: true,
pathRewrite: {
[`^/my-service`]: '',
},
}));
// Start Proxy
app.listen(PORT, HOST, () => {
console.log(`Starting Proxy at ${HOST}:${PORT}`);
});
什麼?就這樣?
雖然 proxy 感覺是個很複雜的概念,但有了第三方套件的幫助,是可以快速建立出 http proxy 的(當然如果需要在 proxy 實作複雜的功能就是例外了)
重點在這段 code
這段 code 的意思是幫我們建立一個 proxy middleware,如果 request 的 route 符合 /my-service/* 就會幫我們將 request 轉發到 target URL 去,以我們的例子而言就是 JSONPlaceholder API。pathRewrite 則是可以將指定的 path 替換掉,上面的例子就是把 my-service 取代成空字串,舉個例子,如果我們發一個 request 到 http://localhost:3000/my-service/posts/1,經過 proxy 後實際會將 request 發送到 https://jsonplaceholder.typicode.com/posts/1,my-service 會被空字串取代,而保留 post/1。
接下來試著將程式跑起來看看吧!在 terminal 輸入
node app.js
可以看到 http-proxy-middleware 還很貼心的將 proxy 資訊 log 出來,接著我們在瀏覽器訪問 http://localhost:3000/my-service/posts/1
會發現我們順利取得來自 JSON Placeholder API 的 JSON data 了,然而值得注意的是,雖然我們的 server 實際是到 JSON Placeholder 拿資料,但對於 client 來說,他訪問的依然是 http://localhost:3000/my-service/posts/1 這個 endpoint(看看瀏覽器的 url bar)
從 browser devtool 來看,似乎也看不出有去 JSON Placeholder API 拿資料的蹤跡,這個結果又再次強調了 http proxy 可以處理 client 不需要在乎的邏輯或細節的特性(client 只管呼叫後端提供的 API endpoint,不用在乎資料到底從哪來的,反正最後有給我資料就好)。
https://github.com/kylemocode/2020-it-iron-man-challenge
(http-proxy folder)
今天使用 Node.js 搭配第三方套件實作了一個極簡易的的 http proxy,如果你想繼續嘗試 proxy 的其他功能,這邊有幾個方向可以提供給你:
Proxy 也許不是一個非常難懂的概念,但卻可以應用在複雜的情境中,也可以應用在應用端或硬體端等不同領域中,有興趣的話就親自試試看吧!
想盡辦法當好一個Junior Backend Developer
React 疑難排解